package com.wjv.example.spbt.task.aop;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * DataPermissionAspect
 *
 * @author wjv
 * @date 2023/2/6 11:23
 */

@Aspect
@Component()
@Slf4j
public class DataPermissionAspect implements InitializingBean {

    private LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer;

    private ExpressionParser expressionParser;

    @Override
    public void afterPropertiesSet() throws Exception {
        parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
        expressionParser = new SpelExpressionParser();
    }

    @Pointcut("@annotation(DataPermission)")
    private void pointcut() {
    }

    @Before("pointcut()")
    private void before() {
        log.info("before");

    }

    @Around("pointcut()")
    public Object execute(ProceedingJoinPoint pjp) throws Throwable {
        prepare(pjp);
        return pjp.proceed();
    }

    private void prepare(ProceedingJoinPoint pjp) {
        // 获取被代理方法
        Method method = getMethod(pjp);
        DataPermission dataPermission = method.getAnnotation(DataPermission.class);
        String attributeName = dataPermission.attributeName();

        StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
        // 获取方法参数
        Object[] args = pjp.getArgs();
        // 获取方法参数名称 (使用Spring支持类库)
        String[] paraNameArr = parameterNameDiscoverer.getParameterNames(method);
        // SpEL上下文
        for (int i = 0; i < Objects.requireNonNull(paraNameArr).length; i++) {
            // 把方法参数放入SpEL上下文中
            evaluationContext.setVariable(paraNameArr[i], args[i]);
        }
        // 使用SpEL 对key的解析
        // this.key = expressionParser.parseExpression(this.key).getValue(evaluationContext, String.class);


    }

    /**
     * 获取被拦截方法对象
     * @param joinPoint joinPoint
     * @return
     */
    private Method getMethod(ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        return methodSignature.getMethod();
    }

}
